#include "StdAfx.h"
#include "symulator.h"
#include "konfiguracja.h"
#include <algorithm>
#include "generatory.h"


std::vector<ObiektDyskretny *> zbiorDyskr;


Symulator::Symulator(System::Windows::Forms::Form^ parent) : obiektUstawiony(false) {
   this->parent = parent;
   petla = new PetlaSymulacji();
   //   wektorRegulatorow = new std::vector<int>();
   //   wektorObiektow = new std::vector<int>();
   std::map<std::string,int> wektor = Generator::pobierzDostepneGeneratory();
   std::map<std::string,int>::iterator it = wektor.begin();

   for(; it != wektor.end(); ++it) {
      mapaPustychGeneratorow[ToSysString(it->first)] = it->second;
   }

}

Symulator::~Symulator() {

}

void Symulator::wczytajKonfiguracje() {
   //   usunDyskretne();
   try {
      zbiorDyskr = PlikKonfiguracyjny::pobierzInstancje().wczytaj();

   } catch (...) {
      
   }

   for (int i = 0; i != zbiorDyskr.size(); i++) {
      // --- mamy regulator ---------------------------------------------------------
      Regulator *reg = dynamic_cast<Regulator * > (zbiorDyskr.at(i));
      if (reg) {
	 mapaRegulatorow[ToSysString(zbiorDyskr.at(i)->pobierzNazwe())] = (zbiorDyskr.at(i)->getID());
      }
	
      // ---- mamy ObiektARMAX ---------------------------------------------------------
      ObiektARMAX *ob = dynamic_cast<ObiektARMAX * > (zbiorDyskr.at(i));
      if (ob) {
	 mapaObiektow[ToSysString(zbiorDyskr.at(i)->pobierzNazwe())] = (zbiorDyskr.at(i)->getID());
      }      
   }
   nowyStan(TematAktualizacji::nowaMapaRegulatorow);
   nowyStan(TematAktualizacji::nowaMapaObiektow);
   nowyStan(TematAktualizacji::nowaMapaWartZad);
}

void Symulator::symulatorStart() {
   if(!watekSymulacji) {
      watekSymulacji = gcnew Thread( gcnew ThreadStart(this,&Symulator::petlaSymulacji));
      watekSymulacji->Start();
   } else {
	   if(!watekSymulacji->IsAlive) {
		   watekSymulacji = gcnew Thread( gcnew ThreadStart(this,&Symulator::petlaSymulacji));
		   watekSymulacji->Start();
	   }
   }
}

void Symulator::symulatorStop() {
   if (watekSymulacji) {
      watekSymulacji->Abort();
	  //delete watekSymulacji;
   }

}
void Symulator::symulatorReset() {
   if (watekSymulacji) {
      watekSymulacji->Abort();
	  //delete watekSymulacji;
   }
   petla->reset();
   u = 0;
   y = 0;
}

System::Void Symulator::petlaSymulacji() {
   nowyStan_d^ nowyStanDelegat = gcnew nowyStan_d(this, &Symulator::nowyStan);
   while (true) {
      
      petla->wykonajKrokSymulacji();
      tablicaWartosci.clear();
      tablicaWartosci.push_back(petla->pobierzCzas());
      tablicaWartosci.push_back(petla->pobierzWartoscRegulowana());
      tablicaWartosci.push_back(petla->pobierzWartoscZadana());
      tablicaWartosci.push_back(petla->pobierzSterowanie());
      /* u = petla->pobierzSterowanie();
      y = petla->pobierzWartoscRegulowana();
      w = petla->pobierzWartoscZadana();
      czas = */
      
      //tablicaWartosci = gcnew array <System::Object^>(4) {czas, y, w, u};
      parent->Invoke(nowyStanDelegat,gcnew array<System::Object^>(1){static_cast<int>(TematAktualizacji::nowyKrokSymulacji)});      
      nrProbki++;
      /*RegulatorPIDAdapt* regulatorPIDAdaptPtr = dynamic_cast<RegulatorPIDAdapt*>(petla->);
      if (regulatorPIDAdaptPtr != NULL &&
	  regulatorPIDAdaptPtr->czyKoniecSamonastrajania()) {
	 this->Invoke(aktywujSamonastrajanie, gcnew array<System::Boolean^>(1) {
               true
		  });
		  }*/

      Thread::Sleep(czasProbkowania);
   }
}

void Symulator::dodajObserwatora(Obserwator^ ob) {
   listaObserwatorow.push_back(ob);
}

void Symulator::usunObserwatora(Obserwator^ ob) {
   listaObserwatorow.remove(ob);
}

void Symulator::nowyStan(int zdarzenie) {
   cliext::list<Obserwator^>::iterator it = listaObserwatorow.begin();
   for(; it != listaObserwatorow.end(); ++it) {
      it->aktualizuj(zdarzenie);
   }
}

cliext::map<System::String^,int> Symulator::pobierzMapeRegulatorow() {
   return mapaRegulatorow;
}

cliext::map<System::String^,int> Symulator::pobierzMapeObiektow() {
   return mapaObiektow;
}

cliext::map<System::String^, int> Symulator::pobierzMapeWartZad() {
   return mapaPustychGeneratorow;
}

cliext::vector<System::String^> Symulator::pobierzListeUstawionychGeneratorow() {
   return wektorDodanychGeneratorow;
}

void Symulator::ustawRegulator(System::String^ nazwa) {
   cliext::map<System::String^, int>::iterator mapIt = mapaRegulatorow.find(nazwa);
   if(mapIt != mapaRegulatorow.end()){
      PorownajWskaznikZInt<Kolekcja> idRegulatora = {mapIt->second};
   
      try {
	 petla->ustawRegulator(*(find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idRegulatora)));
	 nowyStan(TematAktualizacji::zmianaRegulatora);
      } catch(...) {
	 //moze_gdzies_to_zapisac
      }

   } 
}

void Symulator::ustawObiekt(System::String^ nazwa) {
   cliext::map<System::String^, int>::iterator mapIt = mapaObiektow.find(nazwa);
   if(mapIt != mapaObiektow.end()){
      PorownajWskaznikZInt<Kolekcja> idObiektu = {mapIt->second};
      std::vector<ObiektDyskretny*>::iterator it;
      try {
	 if(obiektUstawiony) {
	    petla->usunObiekt(1); //symulator ograniczna mozliwosc nieskonczonej liczby obiektow
	 }
	 if((it = find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idObiektu)) != zbiorDyskr.end()) {
	    petla->dodajObiekt(*(find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idObiektu)));
	    nowyStan(TematAktualizacji::zmianaObiektu);
		obiektUstawiony = true;
	 }
      } catch(...) {
	 //moze_gdzies_to_zapisac
      }

   }
}

void Symulator::dodajWartZad(System::String^ nazwa) {
   cliext::map<System::String^, int>::iterator mapIt = mapaPustychGeneratorow.find(nazwa);
   if(mapIt != mapaPustychGeneratorow.end()){
      switch(mapIt->second) {
      case Generatory::Losowy:
	 petla->dodajGenerator(new GeneratorLosowy());
	 break;

      case Generatory::Trojkat:
	 petla->dodajGenerator(new GeneratorTrojkata());
	 break;

      case Generatory::Sinus:
	 petla->dodajGenerator(new GeneratorSinusa());
	 break;

      case Generatory::Impuls:
	 petla->dodajGenerator(new GeneratorImpulsu());
	 break;

      case Generatory::Prostokat:
	 petla->dodajGenerator(new GeneratorProstokata());
	 break;
      
      
   case Generatory::Skok:
	 petla->dodajGenerator(new GeneratorSkoku());
	 break;
      }
      aktualizacjaListyGeneratorowSymulatora();
      nowyStan(TematAktualizacji::nowaListaUstawionychGeneratorow);
   }
}

void Symulator::aktualizacjaListyGeneratorowSymulatora() {
   std::vector<std::string> generatory = petla->pokazUstawioneGeneratory();
   std::vector<std::string>::iterator it = generatory.begin();
   wektorDodanychGeneratorow.clear();
   for(; it != generatory.end(); ++it) {
      wektorDodanychGeneratorow.push_back(ToSysString(*it));
   }   
}

void Symulator::usunWartZad(System::String^ nazwa) {
   
}


std::map<std::string, std::string> Symulator::pobierzKonfigRegulatora() {   
   return petla->pobierzKonfigRegulatora();
}

std::map<std::string, std::string> Symulator::pobierzKonfigObiektu() {   
   return petla->pobierzKonfigObiektu();
}

std::map<std::string, std::string> Symulator::pobierzKonfigGeneratora(std::string nazwa) {
   return petla->pobierzKonfigWartZad(nazwa);
}

cliext::vector<double> Symulator::pobierzAktualneWartosci() {
   return tablicaWartosci;
}

void Symulator::ustawCzasProbkowania(int czasProbkowania) {
   this->czasProbkowania = czasProbkowania;
}

void Symulator::zmienParametryRegulatora(std::map<std::string,std::string> konfig) {
   if(petla->ustawParametryObiektu(konfig)) {
      nowyStan(TematAktualizacji::zmianaRegulatora);
   }
}
void Symulator::zmienParametryGeneratora(std::string nazwa, std::map<std::string,std::string> konfig) {
   petla->ustawParametryGeneratora(nazwa,konfig);
}
